package com.habook.ui;

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Cursor;
import java.awt.Event;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;

import javax.swing.AbstractAction;
import javax.swing.BorderFactory;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JMenuItem;
import javax.swing.JPanel;
import javax.swing.JPopupMenu;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.JTextField;
import javax.swing.KeyStroke;
import javax.swing.event.UndoableEditEvent;
import javax.swing.event.UndoableEditListener;
import javax.swing.text.Document;
import javax.swing.text.JTextComponent;
import javax.swing.undo.CannotRedoException;
import javax.swing.undo.CannotUndoException;
import javax.swing.undo.UndoManager;

import com.habook.image.ImageHelper;
import com.habook.util.JackMail;
import com.habook.util.Property;

public class HandyNotesPanel extends JPanel {

	private static final long serialVersionUID = -7032125147534558126L;

	private JTextArea noteTextArea = new JTextArea(Property.loadLocalNote());
	private JTextField notePathField = new JTextField(Property.getAbsLocalNotePath());
	private JMenuItem syncMailItem = new JMenuItem("Sync mail", ImageHelper.ICON_MAIL_SEND);
	private JMenuItem configMailItem = new JMenuItem("Config mail");
	private JMenuItem usageItem = new JMenuItem("Usage");
	private JMenuItem aboutItem = new JMenuItem("About");

	public HandyNotesPanel() {

		syncMailItem.setMnemonic('S');
		syncMailItem.setAccelerator(KeyStroke.getKeyStroke('S', Event.CTRL_MASK, true));
		syncMailItem.addActionListener(new ActionListener() {
			@Override
			public void actionPerformed(ActionEvent e) {
				String content = noteTextArea.getText();
				if (syncMail(content)) {
					String lastSyncNote = Property.loadLastSyncNote();
					noteTextArea.setText(lastSyncNote);
					saveLocalNote(lastSyncNote);
					updateMyUI();
				}
			}
		});

		notePathField.setEditable(false);
		notePathField.setBorder(BorderFactory.createEmptyBorder());
		notePathField.setCursor(new Cursor(Cursor.TEXT_CURSOR));

		aboutItem.setMnemonic('A');

		JMenu file = new JMenu("File");
		file.setMnemonic('F');
		file.add(syncMailItem);
		JMenu settings = new JMenu("Settings");
		settings.add(configMailItem);
		JMenu help = new JMenu("Help");
		help.setMnemonic('H');
		help.add(usageItem);
		help.add(aboutItem);

		JMenuBar menubar = new JMenuBar();
		menubar.add(file);
		menubar.add(notePathField);
		menubar.add(settings);
		menubar.add(help);

		noteTextArea.setLineWrap(true);
		noteTextArea.setWrapStyleWord(true);
		noteTextArea.setTabSize(4);
		setUndoRedo(noteTextArea);
		setPopupMenu(noteTextArea);
		noteTextArea.addKeyListener(new NoneKeyListener() {
			@Override
			public void keyReleased(KeyEvent e) {
				String content = noteTextArea.getText();
				saveLocalNote(content);
				updateMyUI();
			}
		});

		setLayout(new BorderLayout());
		add(menubar, BorderLayout.NORTH);
		add(new JScrollPane(noteTextArea, JScrollPane.VERTICAL_SCROLLBAR_ALWAYS, //
				JScrollPane.HORIZONTAL_SCROLLBAR_NEVER), BorderLayout.CENTER);
		updateMyUI();
	}

	private void updateMyUI() {
		String text = noteTextArea.getText();
		boolean same = text.equals(Property.loadLastSyncNote());
		if (same) {
			syncMailItem.setEnabled(false);
			notePathField.setForeground(Color.BLACK);
		} else {
			syncMailItem.setEnabled(true);
			notePathField.setForeground(Color.RED);
		}
	}

	private void setPopupMenu(final JTextComponent textComponent) {
		final JPopupMenu popupMenu = new JPopupMenu();
		JMenuItem popupUndoItem = new JMenuItem("Undo", ImageHelper.ICON_UNDO);
		JMenuItem popupCutItem = new JMenuItem("Cut");
		JMenuItem popupCopyItem = new JMenuItem("Copy");
		JMenuItem popupPasteItem = new JMenuItem("Paste");
		JMenuItem popupDeleteItem = new JMenuItem("Delete");
		JMenuItem popupSelectAllItem = new JMenuItem("Select All");

		popupMenu.add(popupUndoItem);
		popupMenu.addSeparator();
		popupMenu.add(popupCutItem);
		popupMenu.add(popupCopyItem);
		popupMenu.add(popupPasteItem);
		popupMenu.add(popupDeleteItem);
		popupMenu.addSeparator();
		popupMenu.add(popupSelectAllItem);

		textComponent.addMouseListener(new MouseAdapter() {
			public void mouseReleased(MouseEvent e) {
				if (e.getButton() == MouseEvent.BUTTON3 && e.isPopupTrigger()) {
					popupMenu.show(e.getComponent(), e.getX(), e.getY());
				}
			}
		});
		popupCopyItem.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent e) {
				textComponent.copy();
			}
		});
		popupPasteItem.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent e) {
				textComponent.paste();
			}
		});
	}

	private void setUndoRedo(JTextComponent textComponent) {
		final UndoManager undo = new UndoManager();
		Document doc = textComponent.getDocument();

		doc.addUndoableEditListener(new UndoableEditListener() {
			public void undoableEditHappened(UndoableEditEvent evt) {
				undo.addEdit(evt.getEdit());
			}
		});

		textComponent.getActionMap().put("Undo", new AbstractAction("Undo") {
			private static final long serialVersionUID = 826782979408395485L;

			public void actionPerformed(ActionEvent evt) {
				try {
					if (undo.canUndo()) {
						undo.undo();
					}
				} catch (CannotUndoException e) {
				}
			}
		});
		textComponent.getInputMap().put(KeyStroke.getKeyStroke("control Z"), "Undo");

		textComponent.getActionMap().put("Redo", new AbstractAction("Redo") {
			private static final long serialVersionUID = 4209209027576340219L;

			public void actionPerformed(ActionEvent evt) {
				try {
					if (undo.canRedo()) {
						undo.redo();
					}
				} catch (CannotRedoException e) {
				}
			}
		});
		textComponent.getInputMap().put(KeyStroke.getKeyStroke("control Y"), "Redo");
	}

	private boolean saveLocalNote(String note) {
		// if (Property.DEBUG)
		// System.out.println("Handy Notes - save local note");
		return Property.saveLocalNote(note);
	}

	private boolean syncMail(String text) {
		// if (Property.DEBUG)
		// System.out.println("Handy Notes - sync mail");
		return JackMail.syncMail(text); // Version Control and set LastSyncNote if Success
	}
}

abstract class NoneKeyListener implements KeyListener {
	@Override
	public void keyPressed(KeyEvent e) {
	}

	@Override
	public void keyReleased(KeyEvent e) {
	}

	@Override
	public void keyTyped(KeyEvent e) {
	}
}
